package com.gitee.wsl.scheduler.job.repository.sample

import com.gitee.wsl.concurrent.collections.ConcurrentMutableMap
import com.gitee.wsl.scheduler.job.InMemKJob
import com.gitee.wsl.scheduler.job.bean.JobLock
import com.gitee.wsl.scheduler.job.repository.LockRepository
import com.gitee.wsl.time.isAfter
import kotlin.time.Clock
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.ExperimentalTime
import kotlin.uuid.ExperimentalUuidApi
import kotlin.uuid.Uuid

@OptIn(ExperimentalUuidApi::class, ExperimentalTime::class)
class MemoryLockRepository(private val conf: InMemKJob.Configuration = InMemKJob.Configuration(),
                           private val clock: Clock = Clock.System
): LockRepository {

    constructor(clock: Clock = Clock.System,
                conf: InMemKJob.Configuration.() -> Unit
    ) : this(InMemKJob.Configuration().also(conf), clock)

    private val map = ConcurrentMutableMap<Uuid, JobLock>()

    override suspend fun ping(id: Uuid): JobLock {
        val lock = JobLock(id, clock.now())
        map[id] = lock
        return lock
    }

    override suspend fun exists(id: Uuid): Boolean {
        val lock = map[id]
        return lock == null || lock.updatedAt.plus((conf.expireLockInMinutes * 60).milliseconds).isAfter(clock.now())
    }

    internal fun deleteAll(): Unit {
        map.clear()
    }

    companion object{
        val DEFAULT = MemoryLockRepository()
    }
}

val LockRepository.Companion.Memory get() = MemoryLockRepository.DEFAULT

@OptIn(ExperimentalTime::class)
fun LockRepository.Companion.Memory(
    conf: InMemKJob.Configuration = InMemKJob.Configuration()
):LockRepository = MemoryLockRepository(conf)
